#ifndef PRIORITY_LIST_H
#define PRIORITY_LIST_H

#include <iostream>
#include "Screen.h"

class PriorityListNode
{
    // Fields
    private:
        PriorityListNode* nextNode;
        PriorityListNode* lastNode;
        Screen* value;
        int priority;

    // Methods
    public:
        PriorityListNode(Screen* v, int p, PriorityListNode* last, PriorityListNode* next)
        {
            lastNode = last;
            nextNode = next;
            value = v;
            priority = p;
        }
        virtual ~PriorityListNode(){};
        PriorityListNode* getNext()
        {
            return nextNode;
        }
        void setNext(PriorityListNode* next)
        {
            nextNode = next;
        }
        PriorityListNode* getLast()
        {
            return lastNode;
        }
        void setLast(PriorityListNode* last)
        {
            lastNode = last;
        }
        int getPriority()
        {
            return priority;
        }
        Screen* getValue()
        {
            return value;
        }
        void setValue(Screen* v)
        {
            value = v;
        }
};

/*
Priority List Characteristics:
 + Ordered (upon insertion) by a specified priority.
 + No duplicate values: Upon insertion, duplicate values are instead moved to
   the end for its given priority level.
 + Doubly-linked list traversal that priority queues do not always offer.

Why a list implementation?
 + Element adding and removing will be infrequent.
   + Random access speed is not so important.
   + Easy to add/remove elements.
 + Fast traversal.
 + In terms of design, it makes more sense for each node to know only
   about its neighbors. Associating an index/key is odd since the list will
   only be access from front-to-back or back-to-front.
Note: Using a vector may yield faster slightly traversal times.

It takes the principles of a priority queue, list, and map
and merges them into one simple data structure.

It has a very basic iteration support without utilising of boost or STL.
*/
class PriorityList
{
    // Fields
    private:
        PriorityListNode* root;
        PriorityListNode* position;
        unsigned int count;     // Number of elements

    // Methods
    public:
        PriorityList();
        virtual ~PriorityList(){};
        void add(Screen* value, int priority);  // Add screen to list, or move it up if already exists
        void print();           // Prints information about all nodes in the list
        unsigned int size();    // Size of list
        bool hasNext();         // Checks if the next position pointer has an initialized value
        Screen* getNext();      // Retrieves next pointer value. Use hasNext() before using this method
        void resetPosition();   // Resets next position pointer to the beginning olf the list
        bool contains(std::string screenName);  // Returns true of list contains a screen with the same name
    private:
        void insert(PriorityListNode* node, PriorityListNode* last, PriorityListNode* next);
        void remove(PriorityListNode* node);
        bool isSame(PriorityListNode* n1, PriorityListNode* n2);
};

#endif
